package com.github.cosycode.imgtool.util;

import com.github.cosycode.common.lang.BaseRuntimeException;
import com.github.cosycode.common.lang.NotSupportException;
import com.github.cosycode.common.util.io.FileSystemUtils;
import com.github.cosycode.common.util.io.IoUtils;
import com.github.cosycode.common.util.otr.PrintTool;
import lombok.NonNull;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.*;

public class FileCleanUtils {

    private static final boolean IS_OS_MAC = System.getProperty("os.name").toLowerCase().contains("mac");

    /**
     * 扫描出 pathname 中 length 小于 maxLength 的小文件
     *
     * @param pathName  待扫描的文件路径
     * @param maxLength 文件最大长度
     */
    public static void scanAndPrintSmallFile(String pathName, int maxLength) throws FileNotFoundException {
        final File rootPath = new File(pathName);
        // 获取根路径 url, 并将符合条件的 markdown 文件添加到 list 表
        FileSystemUtils.fileDisposeByRecursion(rootPath, f -> {
            if (f.length() < maxLength) {
                try {
                    String content = IoUtils.readFile(f);
                    PrintTool.info("{}:({}) ==> \n   content:{}", f.getPath(), f.length(), content);
                } catch (IOException e) {
                    throw new BaseRuntimeException("", e);
                }
            }
        }, f -> {
            if (f.isDirectory()) {
                return true;
            }
            return f.isFile() && f.getName().endsWith(".md");
        });
    }

    public static List<File> scanEmptyDirFile(@NonNull File file) {
        if (!file.isDirectory()) {
            throw new IllegalArgumentException(PrintTool.format("dir 不是合法的文件夹: {}", file.getAbsolutePath()));
        }
        List<File> emptyList = new ArrayList<>();
        // 找出所有空文件夹
        for (LinkedList<File> list = new LinkedList<>(Collections.singletonList(file)); !list.isEmpty(); ) {
            final File first = list.pollFirst();
            if (first.isDirectory()) {
                File[] listFiles = first.listFiles();
                if (listFiles == null || isNoExistActiveFile(listFiles)) {
                    emptyList.add(first);
                } else {
                    Arrays.stream(listFiles).filter(File::isDirectory).forEach(list::add);
                }
            }
        }
        return emptyList;
    }

    /**
     * 删除 file 目录下的空文件夹
     *
     * @param file   文件夹
     * @param dryRun 干跑
     */
    public static void clearEmptyDir(@NonNull File file, boolean dryRun) {
        List<File> emptyList = scanEmptyDirFile(file);
        if (emptyList.isEmpty()) {
            return;
        }
        // 对空文件夹进行处理
        if (dryRun) {
            emptyList.forEach(f -> PrintTool.info("[emptyDir] => {}", f.getAbsolutePath()));
        } else {
            emptyList.forEach(FileCleanUtils::deleteEmptyDirCascade);
        }
    }

    /**
     * 判断一个文件夹是否是用户空目录
     * <p>
     * 空目录表示没有用户的有效文件的目录,
     * <br/> 在 window 中就是空文件夹
     * <br/> 在 mac 中, 仅仅存在 .DS_Store 文件的文件夹依然视为 用户空目录
     * </p>
     *
     * @param file 需要保证 file 是目录
     * @return file 是否是空文件夹
     * @throws FileNotFoundException file 不存在
     * @throws NotSupportException   如果 file 不是目录则抛出异常
     */
    public static boolean isEmptyDir(@NonNull File file) throws FileNotFoundException {
        if (!file.exists()) {
            throw new FileNotFoundException(file.getPath());
        }
        if (!file.isDirectory()) {
            throw new NotSupportException("此文件不是目录 ==> " + file.getPath());
        }
        File[] listFiles = file.listFiles();
        return listFiles == null || isNoExistActiveFile(listFiles);
    }

    /**
     * 用于协助判断一个文件夹是否是空文件夹.
     *
     * <p>
     * <br/> 在 mac 中, .DS_Store 文件不是有效文件
     * </p>
     *
     * @param listFiles file.listFiles
     * @return listFiles 里面不存在有效文件则返回 true
     */
    private static boolean isNoExistActiveFile(@NonNull File[] listFiles) {
        if (listFiles.length == 0) {
            return true;
        }
        if (IS_OS_MAC) {
            for (File f : listFiles) {
                if (!f.getName().equals(".DS_Store")) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 如果 file 不是空文件夹, 则直接跳出,
     * 如果 file 为空文件夹, 则删除 file 之后, 再对 file 的父文件夹进行递归处理
     *
     * @param file 待扫描的文件对象
     */
    public static void deleteEmptyDirCascade(File file) {
        if (!file.exists()) {
            return;
        }
        while (true) {
            File dir = file;
            File[] listFiles = dir.listFiles();
            if (listFiles == null || listFiles.length == 0) {
                file = file.getParentFile();
                doDeleteFile(dir);
            } else if (IS_OS_MAC && listFiles.length == 1 && listFiles[0].getName().equals(".DS_Store")) {
                file = file.getParentFile();
                doDeleteFile(listFiles[0]);
                doDeleteFile(dir);
            } else {
                break;
            }
        }
    }

    public static void doDeleteFile(File file) {
        String absolutePath = file.getAbsolutePath();
        PrintTool.info("[delete: {}] => {}", file.delete() ? "success" : "fails", absolutePath);
    }

}
